
#pragma once

#include <deque>

#include "fiber-env.h"
#include "mutex.h"
#include "native-mutex.h"

namespace dulymoo {

class FiberContext;

class CooperativeMutex : public IMutex
{
    friend class CooperativeCondition;

public:
    explicit CooperativeMutex(bool recursive=true);
    virtual ~CooperativeMutex();

private:
    CooperativeMutex(const CooperativeMutex&);  // unimplemented
    CooperativeMutex& operator= (const CooperativeMutex&);  // unimplemented

public:
    virtual bool Lock();
    virtual bool TryLock();
    virtual void Unlock();

private:
    static void CompleteLock(FiberEnv::ThreadContext*, void*);

private:
    const bool recursive_;
    NativeMutex lock_lock_;
    unsigned int locked_;
    FiberContext *owner_;
    std::deque<FiberContext*> waiting_queue_;
};

} // namespace dulymoo

